import defaultConfig from './default'

// 参考地址：https://developer.mozilla.org/zh-cn/docs/Web/API/XMLHttpRequest

function buildUri(baseUrl, url) {
  let absoluteUrl = ''
  
  if (!baseUrl || /^http(s?):/.test(url)) {
    absoluteUrl = url
  } else {
    absoluteUrl = baseUrl.replace(/\/$/, '') + '/' + url
  }

  return absoluteUrl
}

function forEach(data, fn) {
  if (typeof data !== 'object' || data === null ) {
    return
  }

  const dataType = Object.prototype.toString.call(data)

  if (dataType === '[object Object]') {
    const keys = Object.keys(data)

    for (let key of keys) {
      fn(key, data[key], data)
    } 
  } else {
    data.forEach((val, i) => {
      fn(i, val, data)
    })
  }
}

function isFormData(data) {
  return (typeof data === 'object') && (data instanceof FormData)
}

function isObject(val) {
  return (val !== null) && (typeof val === 'object')
}

function formatRequestData(data, config) {
  if (isObject(data)) {
    config.data = JSON.stringify(data)
    config.headers['Content-Type'] = 'application/json;charset=utf-8'
  }
}

// 如果event.lengthComputable不为真，则event.total等于0
// event.loaded 已经传输的字节
// event.total 需要传输的总字节
function getProgressMsg(event) {
    if (event.lengthComputable) {
        var percentComplete = event.loaded / event.total
        console.log(percentComplete)
    }
}

module.exports = function(config) {
  config = Object.assign(defaultConfig, config)
  
  return new Promise((resovle, reject) => {
    let xhr = new XMLHttpRequest()
    const requestData = formatRequestData(config.data, config)
    const requestHeaders = config.headers

    xhr.onreadystatechange = function () {
      if (xhr.readyState !== xhr.DONE || xhr.status !== 200) {
        return
      }

      const data = xhr.responseType === '' || xhr.responseType === 'text' 
        ? xhr.responseText : xhr.response
      const headers = xhr.getAllResponseHeaders() || {}
      const response = {
        data,
        status: xhr.status,
        statusText: xhr.statusText,
        headers,
        config
      }
      
      resovle(response)
      xhr = null
    } 

    xhr.open(config.method.toLocaleUpperCase(), buildUri(config.baseUrl, config.url), true)

    xhr.responseType = config.responseType
    xhr.timeout = config.xhr
    forEach(requestHeaders, function(key, val) {
      // If data type is Form-Data: delete head and let browser to set
      // If don't have http data to send, then delete the head
      if (key.tolocaleLowerCase === 'content-type' 
        && (requestData === undefined || isFormData(requestData))) {
        delete requestHeaders[key]
      } else {
        xhr.setRequestHeader(key, val)
      }
    })
    xhr.ontimeout = function() { 
      reject('Request timeouted!')
      xhr = null
    }
    xhr.onabort = function() {
      reject('Request aborted!')
      xhr = null
    }
    xhr.onerror = function() {
      reject('Network Error!')
      xhr = null
    } 
    if (typeof config.onDownloadProgress === 'function') {
      xhr.onDownloadProgress = config.onDownloadProgress
    }
    // xhr.upload is about upload object, but not all of the  brower support this property
    if (typeof config.onUploadProgress === 'function' && xhr.upload) {
      xhr.upload.onUploadProgress = config.onUploadProgress
    }

    xhr.send(requestData || null)
  })
}

